package edu.pku.sei.modeler.uml.commands.umlclass;

import edu.pku.sei.modeler.model.common.AbstractFactory;
import edu.pku.sei.modeler.model.common.ModelRegistry;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.structure.MetaLink;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.uml.Artifacts.Artifact;
import edu.pku.sei.modeler.model.uml.Artifacts.Manifestation;
import edu.pku.sei.modeler.model.uml.Dependencies.Dependency;
import edu.pku.sei.modeler.model.uml.Dependencies.Realization;
import edu.pku.sei.modeler.model.uml.Dependencies.Usage;
import edu.pku.sei.modeler.model.uml.Interfaces.Interface;
import edu.pku.sei.modeler.model.uml.Kernel.NamedElement;
import edu.pku.sei.modeler.model.uml.Nodes.Deployment;
import edu.pku.sei.modeler.model.uml.Nodes.Node;
import edu.pku.sei.modeler.uml.commands.ConnectionModelCreateCommand;
import edu.pku.sei.modeler.uml.commands.UMLConnectionCreateCommand;
import edu.pku.sei.modeler.uml.modelHelper.ModelPackage;

public class UMLDependencyCreateCommand extends ConnectionModelCreateCommand {

	public UMLDependencyCreateCommand(MetaModelElement connectionModel,
			MetaModelElement sourceModel) {
		super(connectionModel, sourceModel);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean canExecute() {
		if (connectionModel instanceof Deployment){
			if (sourceModel instanceof Artifact
				&& targetModel instanceof Node) {
				return true;
			} else {
				return false;
			}
		} else {
			return true;
		}
	}

	@Override
	public void execute() {
		MetaModelElement sourceModelElement = sourceModel;
		if (!(sourceModelElement instanceof NamedElement)) {
			return;
		}

		NamedElement sourceElement = (NamedElement) sourceModelElement;
		Dependency dependency = (Dependency) connectionModel;
		// dependency.setModel(this.target.getModelElement().getModel());
		sourceElement.getSupplierDependency().add(dependency);
		// dependency.getSupplierDependency().add(sourceElement);
		dependency.getClientDependency().add(targetModel);
		
		if (sourceModelElement instanceof Artifact){
			if (connectionModel instanceof Deployment && targetModel instanceof Node){
				Node node = (Node) targetModel;
				Deployment deployment = (Deployment) connectionModel; 
				deployment.getDeployedArtifact().add(sourceModel);
				node.getDeployment().add(deployment);
			}else if (connectionModel instanceof Manifestation){
				((Artifact)sourceModel).getManifestation().add(connectionModel);
			}	
		} 
		
		if (connectionModel instanceof Usage
				&& targetModel instanceof Interface
				&& ((Interface) targetModel).getType() == Interface.TYPE_USEINTERFACE) {
			((Usage) dependency).setArrowType(Usage.WITHOUTPORT);
		} else if (connectionModel instanceof Realization
				&& targetModel instanceof Interface
				&& (((Interface) targetModel).getType() == Interface.TYPE_IMPLEMENTINTERFACE
						|| ((Interface) targetModel).getType() == Interface.TYPE_COMPONENTINTERFACE)) {
			((Realization) dependency).setArrowType(Realization.WITHOUTPORT);
		} 
	}

	@Override
	public void undo() {
		MetaModelElement sourceModelElement = sourceModel;
		if (!(sourceModelElement instanceof NamedElement)) {
			return;
		}

		NamedElement sourceElement = (NamedElement) sourceModelElement;
		Dependency dependency = (Dependency) connectionModel;
		sourceElement.getSupplierDependency().remove(dependency);
		// dependency.getSupplierDependency().add(sourceElement);
		dependency.getClientDependency().remove(targetModel);
		
		if (sourceModelElement instanceof Artifact){
			if (connectionModel instanceof Deployment && targetModel instanceof Node){
				Node node = (Node) targetModel;
				Deployment deployment = (Deployment) connectionModel; 
				deployment.getDeployedArtifact().remove(sourceModel);
				node.getDeployment().remove(deployment);
			}else if (connectionModel instanceof Manifestation){
				((Artifact)sourceModel).getManifestation().remove(connectionModel);
			}	
		} 

	}

}
